package com.shut.vehicle.service.impl;

import com.alibaba.fastjson2.JSON;
import com.github.pagehelper.PageHelper;
import com.shut.vehicle.dao.CardNumDao;
import com.shut.vehicle.dao.ServiceRecordDao;
import com.shut.vehicle.pojo.CarNum;
import com.shut.vehicle.pojo.ServiceRecord;
import com.shut.vehicle.service.BookingRecordService;
import com.shut.vehicle.util.JVMBufferUtil;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @author 卢斌
 */
@Slf4j
@Service
public class BookingRecordServiceImpl implements BookingRecordService {

    @Autowired
    private ServiceRecordDao serviceRecordDao;

    @Autowired
    private CardNumDao cardNumDao;

    @Autowired
    private RedissonClient redisson;


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void bookingSnapshot(Integer userId, Integer deviceId, Integer cardId) {
        ServiceRecord unfinishedRecord = serviceRecordDao.getUnfinishedService(userId, deviceId);
        if (unfinishedRecord != null) {
            throw new SecurityException("您还有未完成的预约记录");
        }
        CarNum carNum = cardNumDao.getCardNum(cardId);
        if (carNum == null || !carNum.getUserId().equals(userId)) {
            throw new SecurityException("无效的车牌信息");
        }
        ServiceRecord serviceRecord = new ServiceRecord();
        serviceRecord.setUserId(userId);
        serviceRecord.setDeviceId(deviceId);
        serviceRecord.setCarNum(carNum.getCarNum());
        serviceRecordDao.createServiceRecord(serviceRecord);
        JVMBufferUtil.put(serviceRecord.getCarNum(), serviceRecord.getId().toString());
    }


    @Override
    public List<ServiceRecord> listServiceRecord(Integer userId, Integer deviceId, Boolean hasFinished, Integer pageNum, Integer pageSize) {
        PageHelper.startPage(pageNum, pageSize);
        return serviceRecordDao.listServiceRecord(deviceId, userId, hasFinished);
    }


    @Override
    public void cleanUnFinishedService(Date limitFinishTime) {
        RLock rLock = redisson.getLock("cleanUnFinishedService");
        try {
            boolean lockResult = rLock.tryLock(1, 60, TimeUnit.SECONDS);
            if (! lockResult) {
                return;
            }
        } catch (InterruptedException e) {
            log.info("定时清除过期预约记录上锁异常", e);
        }
        log.info("即将清除过期预约记录");
        List<ServiceRecord> records = serviceRecordDao.listRecordAfterFinishTime(limitFinishTime.toInstant().toEpochMilli());
        log.info("查询到过期预约记录{}个", records.size());
        if (CollectionUtils.isEmpty(records)) {
            return;
        }
        for (ServiceRecord serviceRecord : records) {
            JVMBufferUtil.remove(serviceRecord.getCarNum());
        }
        Set<Integer> ids = records.stream().map(ServiceRecord::getId).collect(Collectors.toSet());
        log.info("清除属两个：{}", records.size());
        serviceRecordDao.cleanUnFinishedService(limitFinishTime, ids);
    }

    /**
     * 所有没有完成的拍照任务加入到缓存中，必须在清理完无效预约记录后调用
     */
    @Override
    public void bufferAllUnfinishedService() {
        List<ServiceRecord> serviceRecords = serviceRecordDao.listServiceRecord(null, null, false);
        if (!serviceRecords.isEmpty()) {
            for (ServiceRecord serviceRecord : serviceRecords) {
                JVMBufferUtil.put(serviceRecord.getCarNum(), serviceRecord.getId().toString());
            }
        }
    }


}
